#ifndef _PROTOCOL_HPP_
#define _PROTOCOL_HPP_
#include "Sock.hpp"
#include <jsoncpp/json/json.h>

namespace ns_protocol
{
// #define MYSELF

#define SPACE " "
#define SPACE_SIZE strlen(SPACE)

#define SEP "\r\n"
#define SEP_SIZE strlen(SEP)

    // 请求
    class Request
    {
    public:
        char _op;
        int _x;
        int _y;

    public:
        Request() = default;

        Request(const char &op, const int &x, const int &y)
            : _op(op), _x(x), _y(y)
        {
        }

        // x op y
        std::string Serialization()
        {
#ifdef MYSELF
            std::string str;

            str += std::to_string(_x);
            str += SPACE;
            str += _op;
            str += SPACE;
            str += std::to_string(_y);

            return str;
#else
        // 请求端序列化
        Json::Value root;

        root["x"]=_x;
        root["y"]=_y;
        root["op"]=_op;

        return Json::FastWriter().write(root);
#endif
        }

        bool Deserialization(const std::string &str)
        {
#ifdef MYSELF
            std::size_t left = str.find(SPACE);
            if (left == std::string::npos)
            {
                return false;
            }

            std::size_t right = str.rfind(SPACE);
            if (right == std::string::npos)
            {
                return false;
            }

            _x = atoi(str.substr(0, left).c_str());
            _y = atoi(str.substr(right + SPACE_SIZE).c_str());
            _op = str[left + SPACE_SIZE];

            return true;
#else
        // 请求端反序列化
        Json::Value root;

        Json::Reader().parse(str,root);

        _x=root["x"].asInt();
        _y=root["y"].asInt();
        _op=root["op"].asInt();

        return true;
#endif
        }
    };

    // 响应
    class Response
    {
    public:
        int _result;
        int _code;

    public:
        Response() = default;

        Response(const int &result, const int &code) : _result(result), _code(code)
        {
        }

        // code result
        std::string Serialization()
        {
#ifdef MYSELF
            std::string str;
            str += std::to_string(_code);
            str += SPACE;
            str += std::to_string(_result);

            return str;
#else
            Json::Value root;
            root["result"]=_result;
            root["code"]=_code;

            return Json::FastWriter().write(root);
#endif
        }

        bool Deserialization(const std::string &str)
        {
#ifdef  MYSELF
            std::size_t pos = str.find(SPACE);
            if (pos == std::string::npos)
            {
                return false;
            }
            _code = atoi(str.substr(0, pos).c_str());
            _result = atoi(str.substr(pos + SPACE_SIZE).c_str());

            return true;
#else
            Json::Value root;

            Json::Reader().parse(str,root);

            _result=root["result"].asInt();
            _code=root["code"].asInt();
            return true;
#endif
        }
    };

    std::string Recv(int sockfd)
    {
        char buffer[1024];

        ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = '\0';
            return std::string(buffer);
        }
        else if (n == 0) // 写端关闭
        {
            std::cerr << "recv return 0" << std::endl;
        }
        else // 读取失败
        {
            std::cerr << "recv error" << std::endl;
        }
        return "";
    }

    bool Recv(int sockfd,std::string *message)
    {
        char buffer[1024];

        ssize_t n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = '\0';
            *message+=buffer;
            return true;
        }
        else if (n == 0) // 写端关闭
        {
            std::cerr << "recv return 0" << std::endl;
        }
        else // 读取失败
        {
            std::cerr << "recv error" << std::endl;
        }
        return false;
    }

    void Send(int sockfd, const std::string &message)
    {
        ssize_t n = send(sockfd, message.c_str(), message.size(), 0);
        if (n < 0)
            std::cerr << "send error" << std::endl;
    }

    // length\r\n123 + 456\r\n...
    std::string DeCode(std::string &message)
    {
        std::size_t pos=message.find(SEP);
        if(pos==std::string::npos)
        {
            return "";
        }

        int length=atoi(message.substr(0,pos).c_str());

        int size=static_cast<int>(message.size())-pos-2*SEP_SIZE;

        if(size>=length)
        {
            message.erase(0,pos+SEP_SIZE); // length\r\n123 + 456\r\n...  --> 123 + 456\r\n...
            std::string str=message.substr(0,length); // 123 + 456
            message.erase(0,length+SEP_SIZE); // 123 + 456\r\n... --> ...

            return str;
        }

        return "";
    }

    std::string EnCode(const std::string &str)
    {
        std::string ret;
        ret+=std::to_string(str.size());
        ret+=SEP;
        ret+=str;
        ret+=SEP;

        return ret;
    }

}

#endif